home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / frntsdk1.cpt / Frontier SDK 1.0 ƒ / BarChart / barchart.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-07  |  22.5 KB  |  1,144 lines

  1.  
  2.  
  3.  
  4. /*⌐ Copyright 1988-1991 UserLand Software, Inc.  All Rights Reserved.*/
  5.  
  6.  
  7. #include <applet.h>
  8.  
  9.  
  10. /*
  11. these are the IAC messages that BarChart can receive from Frontier scripts.
  12.  
  13. for the other side of this interface, check out system.verbs.apps.BarChart in
  14. frontier.root.
  15. */
  16.     #define setbarvaluetoken     'sval'
  17.     #define getbarvaluetoken     'gval'
  18.     #define setbarlabeltoken     'slab'
  19.     #define getbarlabeltoken     'glab'
  20.     #define setbartoken            'sbar'
  21.     #define addbartoken         'abar'
  22.     #define setunitstoken        'sunt'
  23.     #define setbarcounttoken    'scnt'
  24.     #define getbarcounttoken    'gcnt'
  25.     
  26.  
  27.  
  28. #define maxbars 25
  29.  
  30. typedef long tyvalues [maxbars]; /*holds an array worth of values*/
  31.  
  32. #define maxlabelchars 32
  33.  
  34.  
  35. typedef struct tybarrecord {
  36.     
  37.     boolean flhasbeenset: 1; /*avoid displaying if it's never been assigned to*/
  38.     
  39.     long value;
  40.     
  41.     char label [maxlabelchars];
  42.     } tybarrecord;
  43.  
  44.  
  45. typedef struct tybarchartrecord {
  46.     
  47.     short versionnumber; /*this structure is saved on disk*/
  48.     
  49.     boolean flactive: 1; /*true if our window is active, false otherwise*/
  50.     
  51.     boolean flbitmapactive: 1; /*if false use bitmaps in drawing*/
  52.     
  53.     bigstring barunits; /*concatenated at the end of every displayed value*/
  54.     
  55.     short ctbars; /*number of bars in the chart*/
  56.     
  57.     long minvalue, maxvalue; /*the range of values*/
  58.     
  59.     short pixelsbetweenbars; /*how much space between the bars?*/
  60.     
  61.     short onebarwidth; /*how wide is one of the bars?*/
  62.     
  63.     short maxbarheight; /*max height in pixels of a bar*/
  64.     
  65.     short horizbaseline; /*the bottom edge of all the bars*/
  66.     
  67.     short vertbaseline; /*the left edge of the first bar*/
  68.     
  69.     short labelfont, labelsize, labelstyle; /*how are labels drawn?*/
  70.     
  71.     short labelbaseline; /*the horiz baseline for bar labels*/
  72.     
  73.     short labellineheight; /*vertical pixels for a label*/
  74.     
  75.     tybarrecord bars [maxbars];
  76.     } tybarchartrecord, *ptrbarchartrecord, **hdlbarchartrecord;
  77.     
  78.     
  79. bigstring bsbarchartsearch; /*see selectbarchartwindow*/
  80.  
  81. #define pictmargin 20 /*leave this much room on all sides of chart*/
  82.  
  83.  
  84.  
  85.  
  86.  
  87. static boolean setchartconsts (void) {
  88.     
  89.     /*
  90.     set values for the computed and constant fields of the barchart record.
  91.     
  92.     assume non-computed fields have been set and are accurate.
  93.     */
  94.     
  95.     register hdlbarchartrecord hb = (hdlbarchartrecord) app.appdata;
  96.     register hdlappwindow ha = app.appwindow;
  97.     register short totalwidth;
  98.     register short ctbars = (**hb).ctbars;
  99.     Rect r;
  100.     
  101.     (**hb).pixelsbetweenbars = 10;
  102.     
  103.     (**hb).labelfont = (**ha).defaultfont;
  104.     
  105.     (**hb).labelsize = (**ha).defaultsize;
  106.     
  107.     (**hb).labelstyle = (**ha).defaultstyle;
  108.     
  109.     (**hb).labellineheight = (**ha).fontheight;
  110.     
  111.     r = (**ha).windowrect;
  112.     
  113.     totalwidth = (**ha).windowhorizpixels - (2 * pictmargin);
  114.     
  115.     totalwidth -= (ctbars + 1) * (**hb).pixelsbetweenbars;
  116.     
  117.     if (ctbars <= 0) 
  118.         (**hb).onebarwidth = 0; /*defensive driving*/
  119.     else
  120.         (**hb).onebarwidth = totalwidth / ctbars;
  121.     
  122.     (**hb).labelbaseline = r.bottom - pictmargin;
  123.     
  124.     (**hb).horizbaseline = r.bottom - pictmargin - (2 * (**hb).labellineheight);
  125.     
  126.     (**hb).maxbarheight = (**hb).horizbaseline - r.top - pictmargin;
  127.     
  128.     (**hb).vertbaseline = r.left + pictmargin;
  129.     
  130.     return (true);
  131.     } /*setchartconsts*/
  132.     
  133.     
  134. static short getbarleftedge (short barnum) {
  135.  
  136.     register hdlbarchartrecord hb = (hdlbarchartrecord) app.appdata;
  137.  
  138.     return ( 
  139.         (**hb).vertbaseline + 
  140.         
  141.         ((**hb).pixelsbetweenbars * (barnum + 1)) + 
  142.         
  143.         ((**hb).onebarwidth * barnum));
  144.     } /*getbarleftedge*/
  145.     
  146.  
  147. static boolean drawbar (short barnumber) {
  148.     
  149.     register hdlbarchartrecord hb = (hdlbarchartrecord) app.appdata;
  150.     register hdlappwindow ha = app.appwindow;
  151.     register short barnum = barnumber;
  152.     register short maxbarheight = (**hb).maxbarheight;
  153.     register long value = (**hb).bars [barnum].value;
  154.     register long maxvalue = (**hb).maxvalue;
  155.     register short whitearea;
  156.     Rect rbar, rwindow, rbitmap;
  157.     
  158.     if (!(**hb).bars [barnum].flhasbeenset)
  159.         return (true);
  160.         
  161.     rwindow = (**ha).windowrect;
  162.     
  163.     apppushwindow (ha);
  164.     
  165.     rbar.left = getbarleftedge (barnum);
  166.         
  167.     rbar.right = rbar.left + (**hb).onebarwidth;
  168.     
  169.     rbar.bottom = (**hb).horizbaseline;
  170.     
  171.     rbar.top = rbar.bottom - maxbarheight;
  172.     
  173.     rbitmap = rbar;
  174.     
  175.     if (!(**hb).flbitmapactive) /*you can't nest bitmaps*/
  176.         appopenbitmap (rbitmap, ha);
  177.     
  178.     EraseRect (&rbar);
  179.     
  180.     if (maxvalue == 0) /*avoid divide by zero error*/
  181.         whitearea = 0;
  182.         
  183.     else { /*do arithmetic with longs*/
  184.         
  185.         register long l1 = maxvalue - value;
  186.         register long l2 = maxbarheight;
  187.         register long l3 = maxvalue;
  188.         register long l4 = (l1 * l2) / l3;
  189.         
  190.         whitearea = (short) l4;
  191.         }
  192.     
  193.     if (whitearea > 0)
  194.         rbar.top += whitearea;
  195.     
  196.     pushpen ();
  197.     
  198.     if ((**hb).flactive) {
  199.     
  200.         FillRect (&rbar, quickdrawglobal (gray));
  201.         
  202.         PenPat (quickdrawglobal (black));
  203.         }
  204.     else {
  205.     
  206.         FillRect (&rbar, quickdrawglobal (ltGray));
  207.         
  208.         PenPat (quickdrawglobal (black));
  209.         }
  210.     
  211.     FrameRect (&rbar);
  212.     
  213.     poppen ();
  214.     
  215.     if (!(**hb).flbitmapactive) /*you can't nest bitmaps*/
  216.         appclosebitmap (ha);
  217.     
  218.     apppopwindow ();
  219.     
  220.     return (true);
  221.     } /*drawbar*/
  222.     
  223.     
  224. static boolean drawlabel (short barnumber) {
  225.     
  226.     register hdlbarchartrecord hb = (hdlbarchartrecord) app.appdata;
  227.     register hdlappwindow ha = app.appwindow;
  228.     register hdlstring hstring;
  229.     register short lh = (**hb).labellineheight;
  230.     bigstring bs;
  231.     Rect r;
  232.     
  233.     if (ha == nil)
  234.         return (false);
  235.     
  236.     if (!(**hb).bars [barnumber].flhasbeenset)
  237.         return (true);
  238.         
  239.     apppushwindow (ha);
  240.     
  241.     pushclip ((**ha).windowrect);
  242.         
  243.     r.left = getbarleftedge (barnumber);
  244.         
  245.     r.right = r.left + (**hb).onebarwidth;
  246.     
  247.     r.bottom = (**hb).labelbaseline - lh;
  248.     
  249.     r.top = r.bottom - lh;
  250.     
  251.     copystring ((**hb).bars [barnumber].label, bs);
  252.     
  253.     pushstyle ((**hb).labelfont, (**hb).labelsize, (**hb).labelstyle);
  254.     
  255.     if (!(**hb).flbitmapactive) /*you can't nest bitmaps*/
  256.         appopenbitmap (r, ha);
  257.     
  258.     EraseRect (&r);
  259.     
  260.     centerstring (r, bs);
  261.     
  262.     if (!(**hb).flbitmapactive) /*you can't nest bitmaps*/
  263.         appclosebitmap (ha);
  264.     
  265.     r.bottom += lh;
  266.     
  267.     r.top += lh;
  268.     
  269.     NumToString ((**hb).bars [barnumber].value, bs);
  270.     
  271.     pushstring ((**hb).barunits, bs);
  272.     
  273.     if (!(**hb).flbitmapactive) /*you can't nest bitmaps*/
  274.         appopenbitmap (r, ha);
  275.     
  276.     EraseRect (&r);
  277.     
  278.     centerstring (r, bs);
  279.     
  280.     if (!(**hb).flbitmapactive) /*you can't nest bitmaps*/
  281.         appclosebitmap (ha);
  282.     
  283.     popstyle ();
  284.     
  285.     popclip ();
  286.     
  287.     apppopwindow ();
  288.     
  289.     return (true);
  290.     } /*drawlabel*/
  291.     
  292.     
  293. static void drawbarchart (void) {
  294.     
  295.     register hdlbarchartrecord hb = (hdlbarchartrecord) app.appdata;
  296.     register short i;
  297.     
  298.     for (i = 0; i < (**hb).ctbars; i++) {
  299.     
  300.         drawbar (i);
  301.         
  302.         drawlabel (i);
  303.         } /*for*/
  304.     } /*drawbarchart*/
  305.     
  306.  
  307. static void drawfreemem (void) {
  308.     
  309.     Rect r;
  310.     Str255 s;
  311.     
  312.     r = (*thePort).portRect;
  313.     
  314.     r.top = r.bottom - 15;
  315.     
  316.     r.right -= 20;
  317.     
  318.     EraseRect (&r);
  319.     
  320.     NumToString (FreeMem () / 1024, s);
  321.     
  322.     MoveTo (r.left + 3, r.bottom - 3);
  323.     
  324.     setfontsizestyle (geneva, 9, 0);
  325.     
  326.     DrawString (s);
  327.     
  328.     DrawString ("\pK");
  329.     } /*drawfreemem*/
  330.     
  331.     
  332. static void drawusername (void) {
  333.     
  334.     /*
  335.     use this to test out the FrontierDoScript functionality.
  336.     */
  337.     
  338.     Rect r;
  339.     Str255 s;
  340.     
  341.     if (!FrontierDoScript ("\puser.name", s))
  342.         copystring ("\punknown user", s);
  343.     
  344.     r = (*thePort).portRect;
  345.     
  346.     r.top = r.bottom - 15;
  347.     
  348.     r.right -= 20;
  349.     
  350.     EraseRect (&r);
  351.     
  352.     MoveTo (r.left + 3, r.bottom - 3);
  353.     
  354.     setfontsizestyle (geneva, 9, 0);
  355.     
  356.     DrawString (s);
  357.     } /*drawusername*/
  358.     
  359.     
  360. static void updatebarchart (void) {
  361.     
  362.     register hdlbarchartrecord hb = (hdlbarchartrecord) app.appdata;
  363.     register hdlappwindow ha = app.appwindow;
  364.     
  365.     if (hb == nil) /*no data, it can't be our window*/
  366.         return;
  367.     
  368.     apppushwindow (ha);
  369.     
  370.     drawfreemem ();
  371.     
  372.     /*drawusername ();*/
  373.     
  374.     (**hb).flbitmapactive = true; /*block lower-level bitmaps*/
  375.     
  376.     appopenbitmap ((**ha).windowrect, ha);
  377.     
  378.     drawbarchart ();
  379.     
  380.     appclosebitmap (ha);
  381.     
  382.     (**hb).flbitmapactive = false; /*unblock lower-level bitmaps*/
  383.         
  384.     apppopwindow ();
  385.     } /*updatebarchart*/
  386.     
  387.     
  388. static boolean activatebarchart (boolean flactive) {
  389.     
  390.     /*
  391.     activate or deactivate the indicated BarChart window.  we can't depend
  392.     on the BC globals being properly set because we may be working with a 
  393.     window that's not the frontmost window.
  394.     
  395.     returns true if we consumed the activate.
  396.     */
  397.     
  398.     register hdlappwindow ha = app.appwindow;
  399.     register hdlbarchartrecord hb = (hdlbarchartrecord) app.appdata;
  400.     
  401.     if (hb == nil) /*no data, it can't be our window*/
  402.         return (false);
  403.         
  404.     invalappwindow (ha, false);
  405.         
  406.     (**hb).flactive = flactive;
  407.     
  408.     return (true);
  409.     } /*activatebarchart*/
  410.     
  411.     
  412. static boolean setminmax (void) {
  413.     
  414.     /*
  415.     examine the values array, and reset the min and max, if necessary.
  416.     
  417.     return true if at least one changed, false otherwise.
  418.     */
  419.     
  420.     register hdlbarchartrecord hb = (hdlbarchartrecord) app.appdata;
  421.     register long newmax, newmin;
  422.     register long val;
  423.     register short i;
  424.     
  425.     newmax = intminusinfinity; /*assume only short values*/
  426.     
  427.     for (i = 0; i < (**hb).ctbars; i++) {
  428.         
  429.         val = (**hb).bars [i].value;
  430.         
  431.         if (val > newmax)
  432.             newmax = val;
  433.         } /*for*/
  434.             
  435.     newmin = intinfinity; /*assume only short values*/
  436.     
  437.     for (i = 0; i < (**hb).ctbars; i++) {
  438.         
  439.         val = (**hb).bars [i].value;
  440.         
  441.         if (val < newmin)
  442.             newmin = val;
  443.         } /*for*/
  444.             
  445.     if ((newmax != (**hb).maxvalue) || (newmin != (**hb).minvalue)) {
  446.         
  447.         (**hb).maxvalue = newmax;
  448.         
  449.         (**hb).minvalue = newmin;
  450.         
  451.         return (true);
  452.         }
  453.     
  454.     return (false); /*no change*/
  455.     } /*setminmax*/
  456.     
  457.     
  458. static void smashchartdisplay (boolean flerase) {
  459.  
  460.     register hdlappwindow ha = app.appwindow;
  461.     Rect r;
  462.  
  463.     setchartconsts (); /*reset all the drawing parameters*/
  464.     
  465.     setminmax (); /*min and max might have changed*/
  466.     
  467.     invalappwindow (ha, flerase);
  468.     
  469.     updateappwindow (ha);
  470.     } /*smashchartdisplay*/
  471.     
  472.  
  473. static boolean setbarunits (bigstring bs) {
  474.     
  475.     register hdlbarchartrecord hb = (hdlbarchartrecord) app.appdata;
  476.  
  477.     copystring (bs, (**hb).barunits);
  478.     
  479.     smashchartdisplay (false); /*redraw the whole thing*/
  480.     
  481.     (**app.appwindow).flmadechanges = true;
  482.     
  483.     return (true);
  484.     } /*setbarunits*/
  485.     
  486.     
  487. static boolean setbarvalue (short barnumber, long barvalue) {
  488.     
  489.     register hdlbarchartrecord hb = (hdlbarchartrecord) app.appdata;
  490.  
  491.     if ((barnumber < 0) || (barnumber >= (**hb).ctbars)) /*defensive driving*/
  492.         return (false);
  493.     
  494.     (**hb).bars [barnumber].value = barvalue;
  495.     
  496.     (**hb).bars [barnumber].flhasbeenset = true;
  497.     
  498.     if (setminmax ())
  499.         smashchartdisplay (false); /*redraw the whole thing*/
  500.         
  501.     else {
  502.         drawbar (barnumber);
  503.     
  504.         drawlabel (barnumber);
  505.         }
  506.     
  507.     (**app.appwindow).flmadechanges = true;
  508.  
  509.     return (true);
  510.     } /*setbarvalue*/
  511.     
  512.  
  513. static boolean getbarvalue (short barnumber, long *barvalue) {
  514.     
  515.     register hdlbarchartrecord hb = (hdlbarchartrecord) app.appdata;
  516.  
  517.     *barvalue = 0; /*default returned value*/
  518.     
  519.     if ((barnumber < 0) || (barnumber >= (**hb).ctbars)) /*defensive driving*/
  520.         return (false);
  521.     
  522.     *barvalue = (**hb).bars [barnumber].value;
  523.     
  524.     return (true);
  525.     } /*getbarvalue*/
  526.     
  527.     
  528. static boolean setallvalues (short ct, tyvalues vals) {
  529.     
  530.     register hdlbarchartrecord hb = (hdlbarchartrecord) app.appdata;
  531.     register short i;
  532.     
  533.     for (i = 0; i < ct; i++) {
  534.     
  535.         (**hb).bars [i].value = vals [i];
  536.         
  537.         (**hb).bars [i].flhasbeenset = true;
  538.         } /*for*/
  539.         
  540.     setminmax ();
  541.     
  542.     smashchartdisplay (false); /*redraw the whole thing*/
  543.     
  544.     (**app.appwindow).flmadechanges = true;
  545.  
  546.     return (true);
  547.     } /*setallvalues*/
  548.     
  549.     
  550. static boolean setbarlabel (short barnumber, bigstring bslabel) {
  551.     
  552.     register hdlbarchartrecord hb = (hdlbarchartrecord) app.appdata;
  553.     
  554.     if ((barnumber < 0) || (barnumber >= (**hb).ctbars)) /*defensive driving*/
  555.         return (false);
  556.         
  557.     copystring (bslabel, (**hb).bars [barnumber].label);
  558.     
  559.     (**hb).bars [barnumber].flhasbeenset = true;
  560.     
  561.     drawlabel (barnumber);
  562.     
  563.     (**app.appwindow).flmadechanges = true;
  564.     
  565.     return (true);
  566.     } /*setbarlabel*/
  567.     
  568.  
  569. static boolean setbar (short barnumber, bigstring bslabel, long barvalue) {
  570.     
  571.     /*
  572.     sets both the label and the value for the indicated bar.
  573.     
  574.     this is provided so that a single IAC call can set both.
  575.     */
  576.     
  577.     register hdlbarchartrecord hb = (hdlbarchartrecord) app.appdata;
  578.  
  579.     if ((barnumber < 0) || (barnumber >= (**hb).ctbars)) /*defensive driving*/
  580.         return (false);
  581.     
  582.     if (!setbarlabel (barnumber, bslabel))
  583.         return (false);
  584.         
  585.     return (setbarvalue (barnumber, barvalue));
  586.     } /*setbar*/
  587.     
  588.     
  589. static short addbar (bigstring bslabel, long barvalue) {
  590.     
  591.     /*
  592.     returns the number of the new bar, -1 if it failed.
  593.     */
  594.     
  595.     register hdlbarchartrecord hb = (hdlbarchartrecord) app.appdata;
  596.     register short barnumber = (**hb).ctbars;
  597.     
  598.     (**hb).ctbars++;
  599.     
  600.     setbarvalue (barnumber, barvalue);
  601.     
  602.     if (!setbarlabel (barnumber, bslabel)) {
  603.         
  604.         (**hb).ctbars--;
  605.         
  606.         return (-1);
  607.         }
  608.     
  609.     smashchartdisplay (true);
  610.     
  611.     (**app.appwindow).flmadechanges = true;
  612.  
  613.     return (barnumber);
  614.     } /*addbar*/
  615.     
  616.  
  617. static boolean getbarlabel (short barnumber, bigstring bslabel) {
  618.     
  619.     register hdlbarchartrecord hb = (hdlbarchartrecord) app.appdata;
  620.     
  621.     setemptystring (bslabel); /*default returned value*/
  622.     
  623.     if ((barnumber < 0) || (barnumber >= (**hb).ctbars)) /*defensive driving*/
  624.         return (false);
  625.     
  626.     copystring ((**hb).bars [barnumber].label, bslabel);
  627.     
  628.     return (true);
  629.     } /*getbarlabel*/
  630.     
  631.  
  632. static boolean resetbarchartwindow (short ctbars) {
  633.     
  634.     (**(hdlbarchartrecord) app.appdata).ctbars = ctbars;
  635.     
  636.     smashchartdisplay (false);
  637.     
  638.     (**app.appwindow).flmadechanges = true;
  639.  
  640.     return (true);
  641.     } /*resetbarchartwindow*/
  642.     
  643.     
  644. static boolean bcnewrecord (void) {
  645.     
  646.     register hdlbarchartrecord hb;
  647.     register short i;
  648.     
  649.     if (!newclearhandle (longsizeof (tybarchartrecord), (Handle *) &app.appdata))
  650.         return (false);
  651.         
  652.     hb = (hdlbarchartrecord) app.appdata;
  653.     
  654.     (**hb).versionnumber = 1;
  655.     
  656.     (**hb).ctbars = 0;
  657.     
  658.     (**hb).minvalue = 0;
  659.     
  660.     (**hb).maxvalue = 0;
  661.     
  662.     (**hb).pixelsbetweenbars = 10;
  663.     
  664.     for (i = 0; i < maxbars; i++) {
  665.         
  666.         (**hb).bars [i].value = 0;
  667.         
  668.         setstringlength ((**hb).bars [i].label, 0);
  669.         } /*for*/
  670.     
  671.     setchartconsts ();
  672.     
  673.     return (true);
  674.     } /*bcnewrecord*/
  675.  
  676.  
  677. static boolean bcdisposerecord (void) {
  678.     
  679.     disposehandle ((Handle) app.appdata);
  680.         
  681.     return (true);
  682.     } /*bcdisposerecord*/
  683.     
  684.     
  685. static boolean bcadjustcursor (void) {
  686.  
  687.     arrowcursor (); /*BarChart's "adjust cursor" is pretty simple*/
  688.     
  689.     return (true);
  690.     } /*bcadjustcursor*/
  691.  
  692.  
  693. static boolean bcwindowresize (void) {
  694.  
  695.     setchartconsts (); /*reset all computed values*/
  696.     
  697.     return (true);
  698.     } /*bcwindowresize*/
  699.     
  700.  
  701. static boolean bcactivate (flactivate) boolean flactivate; {
  702.     
  703.     activatebarchart (flactivate);
  704.     
  705.     return (true);
  706.     } /*bcactivate*/
  707.     
  708.  
  709. static boolean bcupdate (void) {
  710.     
  711.     updatebarchart ();
  712.     
  713.     return (true);
  714.     } /*bcupdate*/
  715.     
  716.     
  717. static boolean setbarvalueverb (void) {
  718.     
  719.     /*
  720.     verb that sets the value of one of the bars in the target window.
  721.     */
  722.     
  723.     short barnumber;
  724.     long barvalue;
  725.     
  726.     if (!settargetglobals ()) /*this verb requires an open barchart window*/
  727.         return (false);
  728.         
  729.     if (!IACgetshortparam (keyDirectObject, &barnumber))
  730.         return (false);
  731.         
  732.     barnumber--; /*our IAC interface is 1-based, internally we're 0-based*/
  733.         
  734.     if (!IACgetlongparam ('vbar', &barvalue))
  735.         return (false);
  736.         
  737.     return (IACreturnboolean (setbarvalue (barnumber, barvalue)));
  738.     } /*setbarvalueverb*/
  739.     
  740.  
  741. static boolean getbarvalueverb (void) {
  742.     
  743.     /*
  744.     verb that returns the value of one of the bars in the target window.
  745.     */
  746.     
  747.     short barnumber;
  748.     long barvalue;
  749.     
  750.     if (!settargetglobals ()) /*this verb requires an open barchart window*/
  751.         return (false);
  752.         
  753.     if (!IACgetshortparam (keyDirectObject, &barnumber))
  754.         return (false);
  755.         
  756.     barnumber--; /*our IAC interface is 1-based, internally we're 0-based*/
  757.         
  758.     getbarvalue (barnumber, &barvalue);
  759.         
  760.     return (IACreturnlong (barvalue));
  761.     } /*getbarvalueverb*/
  762.     
  763.  
  764. static boolean setbarverb (void) {
  765.     
  766.     /*
  767.     verb that sets both the value and label of one of the bars in the
  768.     target window.
  769.     */
  770.     
  771.     short barnumber;
  772.     bigstring bslabel;
  773.     long barvalue;
  774.     
  775.     if (!settargetglobals ()) /*this verb requires an open barchart window*/
  776.         return (false);
  777.         
  778.     if (!IACgetshortparam (keyDirectObject, &barnumber))
  779.         return (false);
  780.         
  781.     barnumber--; /*our IAC interface is 1-based, internally we're 0-based*/
  782.         
  783.     if (!IACgetstringparam ('lbar', bslabel))
  784.         return (false);
  785.         
  786.     if (!IACgetlongparam ('vbar', &barvalue))
  787.         return (false);
  788.  
  789.     return (IACreturnboolean (setbar (barnumber, bslabel, barvalue)));
  790.     } /*setbarverb*/
  791.     
  792.     
  793. static boolean setbarlabelverb (void) {
  794.     
  795.     /*
  796.     verb that sets the label of one of the bars in the target window.
  797.     */
  798.     
  799.     short barnumber;
  800.     bigstring bslabel;
  801.     
  802.     if (!settargetglobals ()) /*this verb requires an open barchart window*/
  803.         return (false);
  804.         
  805.     if (!IACgetshortparam (keyDirectObject, &barnumber))
  806.         return (false);
  807.         
  808.     barnumber--; /*our IAC interface is 1-based, internally we're 0-based*/
  809.         
  810.     if (!IACgetstringparam ('lbar', bslabel))
  811.         return (false);
  812.         
  813.     return (IACreturnboolean (setbarlabel (barnumber, bslabel)));
  814.     } /*setbarlabelverb*/
  815.     
  816.     
  817. static boolean addbarverb (void) {
  818.     
  819.     /*
  820.     verb that adds a new bar to the target window with indicated label and
  821.     value.
  822.     */
  823.     
  824.     bigstring bslabel;
  825.     long barvalue;
  826.     
  827.     if (!settargetglobals ()) /*this verb requires an open barchart window*/
  828.         return (false);
  829.         
  830.     if (!IACgetstringparam (keyDirectObject, bslabel))
  831.         return (false);
  832.         
  833.     if (!IACgetlongparam ('vbar', &barvalue))
  834.         return (false);
  835.         
  836.     return (IACreturnshort (addbar (bslabel, barvalue) + 1));
  837.     } /*addbarverb*/
  838.     
  839.     
  840. static boolean setbarcountverb (void) {
  841.     
  842.     /*
  843.     changes the number of bars in the target window.
  844.     */
  845.     
  846.     short ctbars;
  847.     
  848.     if (!settargetglobals ()) /*this verb requires an open barchart window*/
  849.         return (false);
  850.         
  851.     if (!IACgetshortparam (keyDirectObject, &ctbars))
  852.         return (false);
  853.         
  854.     return (IACreturnboolean (resetbarchartwindow (ctbars)));
  855.     } /*setbarcountverb*/
  856.     
  857.  
  858. static boolean getbarcountverb (void) {
  859.     
  860.     /*
  861.     returns the number of bars in the target window.
  862.     */
  863.     
  864.     register hdlbarchartrecord hb;
  865.     
  866.     if (!settargetglobals ()) /*this verb requires an open barchart window*/
  867.         return (false);
  868.         
  869.     return (IACreturnshort ((**(hdlbarchartrecord) app.appdata).ctbars));
  870.     } /*getbarcountverb*/
  871.     
  872.  
  873. static boolean setunitsverb (void) {
  874.     
  875.     /*
  876.     sets the units string of the target window.  this string is displayed
  877.     with the value of each of the bars.
  878.     */
  879.     
  880.     bigstring bs;
  881.     
  882.     if (!settargetglobals ()) /*this verb requires an open barchart window*/
  883.         return (false);
  884.         
  885.     if (!IACgetstringparam (keyDirectObject, bs))
  886.         return (false);
  887.     
  888.     setbarunits (bs);
  889.         
  890.     return (IACreturnboolean (true));
  891.     } /*setunitsverb*/
  892.     
  893.     
  894. static boolean getbarlabelverb (void) {
  895.     
  896.     /*
  897.     returns the label of one of the bars in the target window.  you provide
  898.     us with a bar number.
  899.     */
  900.     
  901.     short barnumber;
  902.     bigstring barlabel;
  903.     
  904.     if (!settargetglobals ()) /*this verb requires an open barchart window*/
  905.         return (false);
  906.         
  907.     if (!IACgetshortparam (keyDirectObject, &barnumber))
  908.         return (false);
  909.         
  910.     barnumber--; /*our IAC interface is 1-based, internally we're 0-based*/
  911.         
  912.     getbarlabel (barnumber, barlabel);
  913.         
  914.     return (IACreturnstring (barlabel));
  915.     } /*getbarlabelverb*/
  916.     
  917.  
  918. static boolean bciacmessage (void) {
  919.     
  920.     switch (IACgetverbtoken ()) {
  921.         
  922.         case setbarvaluetoken:
  923.             setbarvalueverb (); break;
  924.         
  925.         case getbarvaluetoken:
  926.             getbarvalueverb (); break;
  927.             
  928.         case setbarlabeltoken:
  929.             setbarlabelverb (); break;
  930.             
  931.         case setbartoken:
  932.             setbarverb (); break;
  933.             
  934.         case getbarlabeltoken:
  935.             getbarlabelverb (); break;
  936.         
  937.         case addbartoken:
  938.             addbarverb (); break;
  939.             
  940.         case setunitstoken:
  941.             setunitsverb (); break;
  942.                 
  943.         case setbarcounttoken:
  944.             setbarcountverb (); break;        
  945.             
  946.         case getbarcounttoken:
  947.             getbarcountverb (); break;    
  948.             
  949.         default:
  950.             IACnothandlederror (); break;
  951.         } /*switch*/
  952.         
  953.     return (false);
  954.     } /*bciacmessage*/
  955.     
  956.     
  957. static boolean bcpack (hpacked) Handle *hpacked; {
  958.     
  959.     register hdlbarchartrecord hb;
  960.     
  961.     if (!copyhandle (app.appdata, hpacked)) 
  962.         return (false);
  963.         
  964.     hb = (hdlbarchartrecord) *hpacked;
  965.     
  966.     return (true);
  967.     } /*bcpack*/
  968.     
  969.  
  970. static boolean bcunpack (hpacked) Handle hpacked; {
  971.     
  972.     register hdlbarchartrecord hb = (hdlbarchartrecord) hpacked;
  973.     hdlbarchartrecord hcopy;
  974.     
  975.     if ((**hb).versionnumber != 1)
  976.         return (false);
  977.         
  978.     if (!copyhandle ((Handle) hb, (Handle *) &hcopy))
  979.         return (false);
  980.         
  981.     disposehandle (app.appdata);
  982.     
  983.     app.appdata = (Handle) hcopy;
  984.     
  985.     setchartconsts (); /*reset all computed values*/
  986.         
  987.     return (true);
  988.     } /*bcunpack*/
  989.     
  990.     
  991. static boolean bcgetpicture (hpicture) PicHandle *hpicture; {
  992.     
  993.     register hdlbarchartrecord hb = (hdlbarchartrecord) app.appdata;
  994.     register hdlappwindow ha = app.appwindow;
  995.     register WindowPtr w = (**ha).macwindow;
  996.     Rect r = (*w).portRect;
  997.     register PicHandle hp;
  998.     
  999.     *hpicture = nil; /*return value if error*/
  1000.     
  1001.     if (hb == nil) /*no data, it can't be our window*/
  1002.         return (false);
  1003.     
  1004.     pushmacport (w);
  1005.     
  1006.     pushclip (r);
  1007.     
  1008.     *hpicture = OpenPicture (&r);
  1009.     
  1010.     (**hb).flbitmapactive = true; /*block lower-level bitmaps*/
  1011.     
  1012.     drawbarchart ();
  1013.     
  1014.     (**hb).flbitmapactive = false; /*unblock lower-level bitmaps*/
  1015.         
  1016.     ClosePicture ();
  1017.     
  1018.     popclip ();
  1019.     
  1020.     popmacport ();
  1021.     
  1022.     return (true);
  1023.     } /*bcgetpicture*/
  1024.     
  1025.  
  1026. static boolean bcresetscrollbars (void) {
  1027.     
  1028.     return (true);
  1029.     } /*bcresetscrollbars*/
  1030.     
  1031.     
  1032. static boolean bcscroll (void) {
  1033.     
  1034.     return (true);
  1035.     } /*bcscroll*/
  1036.     
  1037.     
  1038. static boolean bcopenprint (void) {
  1039.     
  1040.     app.printinfo.ctpages = 1;
  1041.     
  1042.     return (true);
  1043.     } /*bcopenprint*/
  1044.     
  1045.     
  1046. static boolean bcpagesetup (void) {
  1047.     
  1048.     return (true);
  1049.     } /*bcpagesetup*/
  1050.     
  1051.     
  1052. static boolean bcprintpage (pagenumber) short pagenumber; {
  1053.     
  1054.     PicHandle hpict;
  1055.     Rect rpict, rpaper;
  1056.     short hindent, vindent;
  1057.     
  1058.     if (!bcgetpicture (&hpict))
  1059.         return (false);
  1060.     
  1061.     rpict = (**hpict).picFrame;
  1062.     
  1063.     rpaper = app.printinfo.paperrect;
  1064.     
  1065.     hindent = ((rpaper.right - rpaper.left) - (rpict.right - rpict.left)) / 2;
  1066.     
  1067.     vindent = ((rpaper.bottom - rpaper.top) - (rpict.bottom - rpict.top)) / 2;
  1068.     
  1069.     OffsetRect (&rpict, hindent, vindent);
  1070.     
  1071.     DrawPicture (hpict, &rpict);
  1072.     
  1073.     KillPicture (hpict);
  1074.     
  1075.     return (true);
  1076.     } /*bcprintpage*/
  1077.     
  1078.     
  1079. static boolean bccloseprint (void) {
  1080.     
  1081.     return (true);
  1082.     } /*bccloseprint*/
  1083.     
  1084.  
  1085. static boolean bchaveselection (void) {
  1086.     
  1087.     return (false); /*no selection in BarChart*/
  1088.     } /*bchaveselection*/
  1089.     
  1090.     
  1091. static boolean bcselectall (void) {
  1092.     
  1093.     return (false); /*no selection in BarChart*/
  1094.     } /*bcselectall*/
  1095.     
  1096.     
  1097. void main (void) {
  1098.     
  1099.     clearbytes (&app, longsizeof (app)); /*init all fields to 0*/
  1100.     
  1101.     app.creator = 'BARC';
  1102.     
  1103.     app.filetype = 'CHRT';
  1104.     
  1105.     app.statswindow = true;
  1106.     
  1107.     app.newrecordcallback = &bcnewrecord;
  1108.     
  1109.     app.disposerecordcallback = &bcdisposerecord;
  1110.     
  1111.     app.adjustcursorcallback = &bcadjustcursor;
  1112.     
  1113.     app.activatecallback = (tyappbooleancallback) &bcactivate;
  1114.     
  1115.     app.updatecallback = &bcupdate;
  1116.     
  1117.     app.windowresizecallback = &bcwindowresize;
  1118.     
  1119.     app.iacmessagecallback = &bciacmessage;
  1120.     
  1121.     app.packcallback = &bcpack;
  1122.     
  1123.     app.unpackcallback = &bcunpack;
  1124.     
  1125.     app.getpictcallback = (tyapphandleptrcallback) &bcgetpicture;
  1126.     
  1127.     app.resetscrollbarscallback = &bcresetscrollbars;
  1128.     
  1129.     app.scrollcallback = (tyappsscrollcallback) &bcscroll;
  1130.     
  1131.     app.openprintcallback = &bcopenprint;
  1132.     
  1133.     app.pagesetupcallback = &bcpagesetup;
  1134.     
  1135.     app.printpagecallback = (tyappshortcallback) &bcprintpage;
  1136.     
  1137.     app.closeprintcallback = &bccloseprint;
  1138.     
  1139.     app.haveselectioncallback = &bchaveselection;
  1140.     
  1141.     app.selectallcallback = &bcselectall;
  1142.     
  1143.     runapplet ();
  1144.     } /*main*/